/*
 * Copyright (C) 2011, EADS France
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 */
package xowl.gmi.view.diagram;

import java.util.List;
import xowl.gmi.environment.Locale;

/**
 *
 * @author Laurent WOUTERS
 */
public class SelectableWidget extends Widget {
    public static interface Actions {
        void onSelected();
        void onUnselected();
        void onMenuCut();
        void onMenuCopy();
        void onMenuRemove();
        void onMenuDelete();
        void onMenuExecute(String id);
    }
    
    protected Actions actions;
    protected Widget sub;
    protected javax.swing.JPopupMenu menu;
    protected javax.swing.JMenu menuExecute;
    protected boolean isHovered;
    protected boolean isSelected;
    
    public SelectableWidget(Actions actions, Locale locale) {
        this.actions = actions;
        menu = new javax.swing.JPopupMenu();
        javax.swing.JMenuItem itemCut = new javax.swing.JMenuItem(locale.editCut_text, xowl.gmi.view.IconProvider.getEmbedded(locale.editCut_icon));
        itemCut.addMouseListener(new java.awt.event.MouseAdapter() {
            @Override public void mouseReleased(java.awt.event.MouseEvent evt) { SelectableWidget.this.actions.onMenuCut(); }
        });
        javax.swing.JMenuItem itemCopy = new javax.swing.JMenuItem(locale.editCopy_text, xowl.gmi.view.IconProvider.getEmbedded(locale.editCopy_icon));
        itemCopy.addMouseListener(new java.awt.event.MouseAdapter() {
            @Override public void mouseReleased(java.awt.event.MouseEvent evt) { SelectableWidget.this.actions.onMenuCopy(); }
        });
        javax.swing.JMenuItem itemRemove = new javax.swing.JMenuItem(locale.editRemove_text, xowl.gmi.view.IconProvider.getEmbedded(locale.editRemove_icon));
        itemRemove.addMouseListener(new java.awt.event.MouseAdapter() {
            @Override public void mouseReleased(java.awt.event.MouseEvent evt) { SelectableWidget.this.actions.onMenuRemove(); }
        });
        javax.swing.JMenuItem itemDelete = new javax.swing.JMenuItem(locale.editDelete_text, xowl.gmi.view.IconProvider.getEmbedded(locale.editDelete_icon));
        itemDelete.addMouseListener(new java.awt.event.MouseAdapter() {
            @Override public void mouseReleased(java.awt.event.MouseEvent evt) { SelectableWidget.this.actions.onMenuDelete(); }
        });
        menuExecute = new javax.swing.JMenu(locale.runMenu_text);
        menuExecute.setIcon(xowl.gmi.view.IconProvider.getEmbedded("execute.png"));
        
        menu.add(itemCut);
        menu.add(itemCopy);
        menu.add(itemRemove);
        menu.add(itemDelete);
    }
    
    public void setChild(Widget sub) { this.sub = sub; }
    
    public void addMenuExecute(final String id, String name) {
        javax.swing.JMenuItem item = new javax.swing.JMenuItem(name, xowl.gmi.view.IconProvider.getEmbedded("play.png"));
        item.addMouseListener(new java.awt.event.MouseAdapter() {
            @Override public void mouseReleased(java.awt.event.MouseEvent evt) { SelectableWidget.this.actions.onMenuExecute(id); }
        });
        menuExecute.add(item);
        if (menu.getComponentIndex(menuExecute) == -1) {
            menu.addSeparator();
            menu.add(menuExecute);
        }
    }
    
    @Override public List<Couple> getVertices() { return sub.getVertices(); }
    
    @Override protected void buildStackChildren(List<Widget> stack, Couple input) {
        if (sub != null)
            sub.buildStackAt(stack, input);
    }
    
    @Override public Couple getMinSize() { return sub.getMinSize(); }
    @Override public Couple getMaxSize() { return sub.getMaxSize(); }
    @Override public Couple layout() {
        dimension = sub.layout();
        sub.setPosition(new Couple(0, 0));
        return dimension;
    }
    @Override public Couple layout(Couple bounds) {
        dimension = sub.layout(bounds);
        sub.setPosition(new Couple(0, 0));
        return dimension;
    }
    @Override public void paint(java.awt.Graphics2D g2d, float alpha, DiagramStyle style, Couple offset) {
        java.awt.Color background = null;
        if (isSelected) background = style.selectableSelectedColor;
        else if (isHovered) background = style.selectableHoverColor;
        if (background != null)
            paintBackground(g2d, style, offset, background);
        sub.paint(g2d, alpha * transparency, style, position.plus(offset));
    }
    @Override protected void exportSVG(org.w3c.dom.Document doc, org.w3c.dom.Element parent, float alpha, DiagramStyle style, Couple offset) {
        sub.exportSVG(doc, parent, alpha * transparency, style, position.plus(offset));
    }
    
    @Override public boolean isSelectable() { return true; }
    @Override public void toggleSelected() {
        isSelected = !isSelected;
        if (isSelected) actions.onSelected();
        else actions.onUnselected();
    }
    
    @Override public boolean onMouseEnter(UserState state, Couple local) {
        if (state != UserState.Normal) return false;
        isHovered = true;
        return true;
    }
    @Override public boolean onMouseLeave() {
        if (!isHovered) return false; 
        isHovered = false;
        return true;
    }
    @Override public boolean onMouseContextMenu(Diagram diagram) {
        diagram.openMenu(menu);
        return true;
    }
    
    protected void paintBackground(java.awt.Graphics2D g2d, DiagramStyle style, Couple offset, java.awt.Color color) {
        int pad = style.selectablePadSize;
        Couple rp = position.plus(offset).minus(pad);
        Couple dim = dimension.plus(pad*2);
        g2d.setColor(color);
        g2d.fillRect((int)rp.x, (int)rp.y, (int)dim.x, (int)dim.y);
    }
}
